package vv.lines.core;

import vv.lines.core.animations.Animation;
import vv.lines.core.animations.AnimationHelper;
import vv.lines.core.context.ContextHolder;

import java.util.Collection;
import java.util.HashSet;
import java.util.List;

/**
 *
 * @author vpotapenko
 */
public class BallController extends ContextHolder {

    private Field field;

    private AnimationHelper animationHelper;
    private BallHolder ballHolder;

    public BallController(Field field) {
        super(field.getContext());
        this.field = field;
        animationHelper = new AnimationHelper(this, field);
        ballHolder = new BallHolder();
    }

    public void dispatchCancelAnimation(Animation animation) {
        updateBounds(animation.getTarget());

        switch (animation.getType()) {
            case HIDE:
                handleCancelHideAnimation();
                break;
            case SHOW:
                field.dispatchNewPreviewBalls(ballHolder.generatedBuffer().asList());
                break;
        }

        field.getView().repaint();
    }

    private void handleCancelHideAnimation() {
        field.updateScore(ballHolder.deletedBuffer().size());
        ballHolder.doRemove();
    }

    void setSelectedBall(Ball selectedBall) {
        final Ball oldSelectedBall = ballHolder.getSelectedBall();
        if (oldSelectedBall != selectedBall) {
            handleChangeSelection(oldSelectedBall, selectedBall);
            ballHolder.setSelectedBall(selectedBall);
        }
    }

    void flushGeneratedBalls() {
        showBallsView(ballHolder.generatedBuffer());
        ballHolder.generatedBuffer().clear();
        ballHolder.generateNewBalls(getContext());
    }

    void setGeneratedBallOnCell(Cell cell) {
        Ball ball = ballHolder.peekGeneratedBall(getContext());

        cell.setBall(ball);

        ball.setField(field);
        ball.setOwner(cell, true);
    }

    public void removeBallFromCells(Collection<Cell> cells) {
        for (Cell cell : cells)
            ballHolder.removeBall(cell.getBall());

        animationHelper.addHideAnimation(ballHolder.deletedBuffer().asList());
    }

    public void moveBall(Ball ball, List<Cell> path) {
        clearSelection();

        path.get(0).setBall(null);
        path.get(path.size() - 1).setBall(ball);

        ball.setOwner(path.get(path.size() - 1), false);
        animationHelper.addMoveAnimation(ball, path);
    }

    public void clearAll() {
        ballHolder.clearAll();
    }

    public void updateBounds() {
        updateBounds(ballHolder.primaryBuffer().asList());
    }

    private void updateBounds(Collection<Ball> balls) {
        for (Ball ball: balls) {
            ball.updateBounds();
            ball.setAlpha(1);
        }
    }

    private void handleChangeSelection(Ball oldBall, Ball newBall) {
        if (oldBall != null) oldBall.setSelected(false);
        if (newBall != null) newBall.setSelected(true);
    }

    public void selectBall(Ball ball) {
        if (ball == null) return;

        clearSelection();
        setSelectedBall(ball);
        animationHelper.addActiveAnimation(ball);
    }

    public void clearSelection() {
        if (ballHolder.getSelectedBall() == null) return;

        setSelectedBall(null);
        animationHelper.stopActiveAnimation();
    }

    private void showBallsView(BallBuffer balls) {
        for (Ball ball : balls) {
            ball.setVisible(true);
            ball.setAlpha(0);
        }
        animationHelper.addShowAnimation(new HashSet<Ball>(balls.asList()));
    }


    public Ball getSelectedBall() {
        return ballHolder.getSelectedBall();
    }
}
